<?php

namespace Application\model;

use Cola\Model;

class AccountModel extends Model
{

    /**
     * 处理账号，通过账号获取数据，如果没有账号数据则插入数据
     * @param $m
     * @return mixed|void
     * @throws \Cola\Exception\DbException
     */
    public function initAccount($m)
    {
        if (!$m->cid) $m->cid = CID;
        $account = $m->account;
        $accountInfos = $this->getLastLoginAccount($account, false, $m->cid);
        // 如果玩家非新增玩家
        if ($accountInfos){
            // 更新账号设备信息
            $this->updateByAccount($account, [
                'model'=>$m->model,
                'brand'=>$m->brand,
                'device'=>$m->deviceCode,
                'last_login_time'=>date('Y-m-d H:i:s'),
            ]);
            $accountInfo = $accountInfos[0];
            if (count($accountInfos) === 1 && empty($accountInfo['sid'])) {
                return $accountInfo;
            }
            $m->loginFlag = 1;
            $ServerModel = $this->model('Server');
            // 判断最后登录时间是否当天
            if ($accountInfo['last_login_time'] < date('Y-m-d')) {
                $m->loginFlag = 2;
            }
            logfile('LoginModel', "account: $account is new: 0 and login flag:".$m->loginFlag);

            $banTime = 0;
            // 如果被封禁，返回加多一个字段
            if ($accountInfo['status'] != 1){
                $banTime = $this->getBanTime($account);
            }
            // 获取出符合的最后一条
            foreach ($accountInfos as $a) {
                $a['banTime'] = $banTime;
                $wheres = [];
                $m->serverWhere && $wheres[] = $m->serverWhere;
                $wheres[] = 'sid ='.$a['sid'];
                $where = implode(' and ',$wheres);
                // 通过区服Id查区服信息
                $server = $ServerModel->getServerInfo($where);
                // 是否显示
                if ($server) {
                    return $a;
                }
            }
            return $accountInfo;
        } else {
            $m->isNew = 1;
            $m->loginFlag = 0;
            logfile('LoginModel', "account:$account is new: 1 and login flag:0");
            $data = $this->insertData([
                    'account'=>$account,
                    'account_name'=>$m->account_name,
                    'open_id'=>$m->openId,
                    'cpid'=>$m->cpid,
                    'ccid'=>$m->ccid,
                    'model'=>$m->model,
                    'brand'=>$m->brand,
                    'device'=>$m->deviceCode,
                    'is_new'=>1]
            );
            return $data;
        }

    }

    private function insertData(array $accountInfo)
    {
        $data['account'] = $accountInfo['account'];
        $data['account_name'] = $accountInfo['account_name'];
        $data['cpid'] = $accountInfo['cpid'];
        $data['ccid'] = $accountInfo['ccid'];
        $data['cid'] = CID;
        $data['last_cid'] = CID;
        $data['open_id'] = $accountInfo['open_id'];
        $data['register_time'] = $accountInfo['register_time'] ?? date('Y-m-d H:i:s');
        $data['create_ip'] = ip();
        $data['last_login_time'] = date('Y-m-d H:i:s');
        $data['last_login_ip'] = ip();
        $data['status'] = 1;
        $data['scene'] = 0;
        $data['is_new'] = $accountInfo['is_new'] ?? 0;
        $data['sid'] = $accountInfo['sid'] ?? 0;
        $data['create_cpid'] = $accountInfo['create_cpid'] ?? '';
        $data['actor_id'] = $accountInfo['actor_id'] ?? 0;
        $data['actor_name'] = $accountInfo['actor_name'] ?? '';
        $data['model'] = $accountInfo['model'] ?? '';
        $data['brand'] = $accountInfo['brand'] ?? '';
        $data['device'] = $accountInfo['device'] ?? '';
        $data['create_time'] = $accountInfo['create_time'] ?? '2024-01-01 00:00:00';
        $res = $this->db->insert($data, 'accounts');
        return $data;
    }

    /**
     * 根据条件获取玩家登录区服列表
     * @param $account
     * @param $checkSid
     * @param $cid
     * @return array
     * @throws \Cola\Exception\DbException
     */
    public function getLastLoginAccount($account, $checkSid=true, $cid = ''): array
    {
        !$cid && $cid = realCID();
        $cids = $this->model('Channel')->getAllCid($cid);
        $cidStr = implode('\',\'',$cids);
        $where = "cid in ('{$cidStr}') and account=?";
        if ($checkSid) $where .= ' and sid>0';
        $values = [$account];

        self::autoAccountCid($where,$values);
        // 通过账号和渠道获取玩家数据
        $sql = "select id, cid,last_cid,sid, cpid, ccid, account, account_name, open_id, register_time, last_login_time, actor_id, actor_name, is_new, is_gm, create_ip, status, scene from accounts where $where order by actor_login_time desc,last_login_time desc ";
        $accountInfos = $this->db->sql($sql,$values);

        if(!$accountInfos){
            $accountInfos = $this->getLastLoginAccountMChannel($account);
        }
        return $accountInfos;
    }

    public function checkChannelAccount($account,$cid = '')
    {
        $ChannelModel = $this->model('Channel');
        $Account = $ChannelModel->realAccount($account,$cid);
        return $Account;
    }


    public function getLastLoginAccountMChannel($account): array
    {
        $data = [$account];
        $where = "account=?";
        self::autoAccountCid($where,$data);
        // 通过账号和渠道获取玩家数据
        $sql = "select id, cid,last_cid,sid, cpid, ccid, account, account_name, open_id, register_time, last_login_time, actor_id, actor_name, is_new, is_gm, create_ip, status, scene from accounts where $where order by actor_login_time desc,last_login_time desc ";
        $accountInfos = $this->db->sql($sql,$data);
        return $accountInfos;
    }


    protected function getBanTime($account)
    {
        $where = "account=? and status=1 and type=2";
        $values = [$account];
        self::autoAccountCid($where,$values);
        $sql = "select ban_time, ban_dt from gm_ban where $where order by ban_time desc";
        $account = $this->db('_backdb')->row($sql,$values);
        $time = 0;
        if ($account) $time = strtotime($account['ban_dt']) + ($account['ban_time']*60);

        return $time;
    }

    /**
     * 获取账号数据
     * @param $account
     * @param $sid
     * @param $actorId
     * @return array
     */
    public function getAccountInfo($account, $sid=0, $actorId=0): array
    {
        $where = " account=? ";
        $data = [$account];
        if ($actorId){
            $where .= " and actor_id=? ";
            $data[] = $actorId;
        }
        if ($sid){
            $where .= " and sid=? ";
            $data[] = $sid;
        }
        self::autoAccountCid($where,$data);
        $sql = "select id, sid, cid,last_cid,open_id, ccid, actor_id, actor_name, status, create_time from accounts where $where order by actor_login_time desc,last_login_time desc ";
        $account = $this->db->row($sql,$data);
        return $account;
    }

    public function getAccountByActor($actor)
    {
        $where = "actor_id='$actor' or actor_name='$actor' ";
        $sql = "select id, sid, open_id, ccid, actor_id, actor_name, status, create_time from accounts where $where";
        $account = $this->db->row($sql);
        return $account;
    }

    public function getAccountByAccount($account): array
    {
        $where = "account=? ";
        $values = [$account];
        self::autoAccountCid($where,$values);
        $sql = "select id, sid, open_id, ccid, actor_id, actor_name, status, create_time from accounts where $where";
        $accounts = $this->db->sql($sql,$values);
        return $accounts;
    }

    /**
     * 插入或者更新玩家信息
     * @param $data
     * @return array
     * @throws \Cola\Exception\DbException
     */
    public function insertOrUpdateActor($data): array
    {
        $create_time = $data['create_time'];
        $accounts = $this->getLastLoginAccount($data['open_id'], false);
        if(!$accounts){
            /*$account = $this->checkChannelAccount($data['open_id'],CID);
            $accounts = $this->getLastLoginAccount($account, false);*/
        }

        logfile('ServerSideModel', "accounts:".json_encode($accounts));
        $account = [];
        if ($accounts) {
            $tag = 1;
            $newAccount = [];
            foreach ($accounts as $a) {
                $data['actor_login_time'] = date('Y-m-d H:i:s');
                // 纯新玩家 直接更新角色信息
                if ($a['is_new']==1 && $a['sid']==0) {
                    // 不更新open_id
                    unset($a['open_id']);
                    $data['create_time'] = $create_time;
                    $res = $this->updateActorById($a['id'], $data);
                    $account  = $data + $a;
                    $tag = 0;
                }
                // 已有账号 只更新最后登录时间和最后登录ip和角色名
                if ($a['sid']==$data['sid']) {
                    $update = [
                        'actor_id'=>$data['actor_id'],
                        'actor_name'=>$data['actor_name'],
                        'actor_login_time'=>$data['actor_login_time'],
                    ];
                    $res = $this->updateActorById($a['id'], $update);
                    $account  = $update + $a;
                    $tag = 0;
                }
                // 获取注册信息 (从其他渠道的进入 第一次的渠道没有关联映射渠道 就已经创建了一个账号，则默认创建新的账号
                $newAccount['account'] = $a['account'];
                $newAccount['account_name'] = $a['account_name'];
                $newAccount['cpid'] = $a['cpid'];
                $newAccount['ccid'] = $a['ccid'];
                $newAccount['register_time'] = $a['register_time'];
                $newAccount['create_ip'] = $a['create_ip'];
                $newAccount['is_gm'] = $a['is_gm'];
            }

            // 滚服玩家，非新玩家和未有账号，则需要插入数据
            if ($tag){
                $data = array_merge($data, $newAccount);
                $data['create_time'] = $create_time;
                $re = $this->insertData($data);
                $account  = $data;
                if ($re){
                    $res = true;
                } else {
                    $res = false;
                }
            }
        }else{

        }

        return [$account,$res ?? false];
    }

    /**
     * 更新玩家信息
     * @param $id
     * @param $row
     * @return int
     * @throws \Cola\Exception\DbException
     */
    public function updateActorById($id, $row): int
    {
        $res = $this->db->update($row, ['id = ?',[$id]], 'accounts');
        return $res;
    }

    /**
     * 通过账号修改状态 主要用于封号/解封账号操作
     * @param $account
     * @param int $status
     * @return int
     * @throws \Cola\Exception\DbException
     */
    public function updateStatusByAccount($account, int $status=0): int
    {
        $where = "account=? ";
        $values = [$account];
        self::autoAccountCid($where,$values);
        return $this->db->update(['status'=>$status], [$where,$values], 'accounts');
    }

    public function updateByAccount($account, $row, $sid=0)
    {
        if (empty($row)) return false;
        $where = "account=? ";
        $values = [$account];
        if ($sid){
            $where .= " and sid=? ";
            $values[] = $sid;
        }
        self::autoAccountCid($where,$values);
        $res = $this->db->update($row, [$where,$values], 'accounts');
        return $res;
    }

    public function updateLastCidByAccount($account,$login_cid,$last_cid)
    {
        $where = "account=? ";
        $values = [$account];
        self::autoAccountCid($where,$values);
        if($login_cid!=$last_cid){
            $res = $this->db->update(['last_cid'=>$login_cid], [$where,$values], 'accounts');
            return true;
        }
        return false;
    }

    public static function autoAccountCid(&$where,&$values){
        $tem = explode(' and ',$where);
        $account = '';
        $k = 0;
        foreach ($tem as $key => $item){
            if(strpos($item,'account')!==false){
                $account = $values[$k] ?? '';
                break;
            }
            if(strpos($item,'?')!==false){
                $k++;
            }
        }
        if($account){
            $part = explode('-', $account)[0] ?? '';
            $where .= ' and account_cid = ? ';
            $values[] = $part;
        }
    }

}